How to copy attachments from a List into a document library via workflow activity - sharepoint-2007

I currently have a task list, some of them contain file attachments. As part of a new workflow I'm creating in MOSS Designer I need to copy the attachments to files in a document library. What is the best way to do this? Is there an activity already made for this? Thanks!

I know it is an old question but for someone out there..
private void MoveAppraisalSupportDocs(SPListItemCollection sourceDocsList, SPList destinationDocsLib)
{
int sourceDocCnt = sourceDocsList.Count;
if (sourceDocCnt > 0)
{
for (int sd = 0; sd < sourceDocCnt; sd++)
{
SPListItem sourceItem = sourceDocsList[sd];
byte[] fileBytes = sourceItem.File.OpenBinary();
string destUrl = destinationDocsLib.RootFolder.Url + "/" + sourceItem.File.Name;
SPFile destFile = destinationDocsLib.RootFolder.Files.Add(destUrl, fileBytes, true /*true means overwrite */);
}
}
}

Related

How do I increase the size of an Azure File Storage CloudFile before I know the file size?

I'm using Azure File Storage to store some files, and I want to create a zip file containing some of these files on the same Azure file share.
This is my code so far:
private void CreateZip(CloudFileDirectory directory) {
if (directory == null) throw new ArgumentNullException(nameof(directory));
var zipFilename = $"{directory.Name}.zip";
var zip = directory.GetFileReference(zipFilename);
if (!zip.Exists()) {
zip.Create(0); // <-- I don't know what size its gonna be!!
using (var zipStream = zip.OpenWrite(null))
using (var archive = new ZipArchive(zipStream, ZipArchiveMode.Create)) {
foreach (var file in directory.ListFilesAndDirectories().OfType<CloudFile>()) {
if (file.Name.Equals(zipFilename, StringComparison.InvariantCultureIgnoreCase))
continue;
using (var fileStream = file.OpenRead()) {
var entry = archive.CreateEntry(file.Name);
using (var entryStream = entry.Open())
fileStream.CopyTo(entryStream); // <-- exception is thrown
}
}
}
}
}
On the line zip.Create(0); this creates an empty file. I then go on to use this file reference to create a zip file, and add stuff to it, but when it gets to the fileStream.CopyTo(entryStream); it throws an exception with this message:
The remote server returned an error: (416) The range specified is invalid for the current size of the resource.
Presumably because the file size is 0 and it's unable to automatically increase the size.
I can create the file with int.MaxValue, but then I get a 2GB file. I can't even work out the size of the file I'm adding to the achive and resize the file to extend it by that amount, because its a zip and its gonna compress and change the file size.
How do I do this?
This issue is more related with System.IO.Compression. I have rewrite your code, please use memory stream instead like the following code. It works fine on my side. Hope it could give you some tips.
public static void CreateZip(CloudFileDirectory directory)
{
if (directory == null) throw new ArgumentNullException(nameof(directory));
var zipFilename = $"{directory.Name}.zip";
var zip = directory.GetFileReference(zipFilename);
if (!zip.Exists())
{
//zip.Create(600000); // <-- I don't know what size its gonna be!!
using (var memoryStream = new MemoryStream())
{
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
foreach (var file in directory.ListFilesAndDirectories().OfType<CloudFile>())
{
if (file.Name.Equals(zipFilename, StringComparison.InvariantCultureIgnoreCase))
continue;
using (var fileStream = file.OpenRead())
{
var entry = archive.CreateEntry(file.Name, CompressionLevel.Optimal);
using (var entryStream = entry.Open())
{
fileStream.CopyTo(entryStream); // <-- exception is thrown
}
}
}
}
memoryStream.Seek(0, SeekOrigin.Begin);
zip.UploadFromStream(memoryStream);
}
}
}

asp.net mvc 5 sent email attachments are damaged

I am trying to send an email using the method described in this tutorial with a model structure form this tutorial and im partially successfull in doing so. The only issue I am having is the fact that files sent as attachments are damaged. I have tried to get it working in so many ways that I lost count. Obviously haven't been trying hard enough since I didn't find the answer, but decided to ask while I continue looking for an answer.
My controller action is as follows:
public async Task<ActionResult> Index( [Bind(Include = "column names..")] Contact contact, HttpPostedFileBase upload){
if (ModelState.IsValid && status)
{
var message = new MailMessage();
if (upload != null && upload.ContentLength > 0)
{
// 4MB -> 4000 * 1024
const int maxFileSize = 4096000;
if (upload.ContentLength < maxFileSize)
{
var document = new File
{
FileName = System.IO.Path.GetFileName(upload.FileName),
FileType = FileType.Document,
ContentType = upload.ContentType
};
var supportedTypes = new[] {"doc", "docx", "pdf", "jpg"};
var extension = System.IO.Path.GetExtension(document.FileName);
if (extension != null)
{
var fileExt = extension.Substring(1);
if (!supportedTypes.Contains(fileExt))
{
ModelState.AddModelError("document", "Wrong format");
return View();
}
//this is the line that sends damaged attachments,
//I believe I should be using document in some way (using reader bit below),
//but whatever I use the code complains or crashes.
message.Attachments.Add(new Attachment(upload.InputStream, Path.GetFileName(upload.FileName)));
using (var reader = new System.IO.BinaryReader(upload.InputStream))
{
document.Content = reader.ReadBytes(upload.ContentLength);
//message.Attachments.Add(new Attachment(document.Content, document.FileName));
}
contact.Files = new List<File> {document};
}
}else
{
ModelState.AddModelError("document", "File too big. Max 4MB.");
}
}
EDIT: A lot of times the code cannot find the file, how do I make sure I give it correct path each time?

Not able to properly download files from azure storage and data are lost too when downloading files

I have 2 files saved on Azure blob storage:
Abc.txt
Pqr.docx
Now i want to create zip files of this 2 files and allow user to download.
I have saved this in my database table field like this:
Document
Abc,Pqr
Now when i click on download then i am getting file like below with no data in it and file extension are lost too like below:
I want user to get exact file(.txt,.docx) in zip when user download zip file.
This is my code:
public ActionResult DownloadImagefilesAsZip()
{
string documentUrl = repossitory.GetDocumentsUrlbyId(id);//output:Abc.txt,Pqr.Docx
if (!string.IsNullOrEmpty(documentUrl))
{
string[] str = documentUrl.Split(',');
if (str.Length > 1)
{
using (ZipFile zip = new ZipFile())
{
int cnt = 0;
foreach (string t in str)
{
if (!string.IsNullOrEmpty(t))
{
Stream s = this.GetFileContent(t);
zip.AddEntry("File" + cnt, s);
}
cnt++;
}
zip.Save(outputStream);
outputStream.Position = 0;
return File(outputStream, "application/zip", "all.zip");
}
}
}
public Stream GetFileContent(string fileName)
{
CloudBlobContainer container = this.GetCloudBlobContainer();
CloudBlockBlob blockBlob = container.GetBlockBlobReference(fileName);
var stream = new MemoryStream();
blockBlob.DownloadToStream(stream);
return stream;
}
public CloudBlobContainer GetCloudBlobContainer()
{
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["StorageConnectionString"].ToString());
CloudBlobClient blobclient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer blobcontainer = blobclient.GetContainerReference("Mystorage");
if (blobcontainer.CreateIfNotExists())
{
blobcontainer.SetPermissions(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Blob });
}
blobcontainer.SetPermissions(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Blob });
return blobcontainer;
}
I want same file to be downloaded when user download zip file.
Can anybody help me with this??
I'm not a web dev, but hopefully this will help. This snippet of code is in a method where I download a list of blobs into a zip file archive using a stream. The list of files had the slashes in all directions, so there's code in here to fix this, and to make sure I'm getting the blob reference with the right text (no URL, and no opening slash if the blob is in a "folder").
I suspect your problem is not using a memory stream or a binary writer. Specificity helps sometimes. Good luck.
using (ZipArchive zipFile = ZipFile.Open(outputZipFileName, ZipArchiveMode.Create))
{
foreach (string oneFile in listOfFiles)
{
//Need the filename, complete with relative path. Make it like a file name on disk, with backwards slashes.
//Also must be relative, so can't start with a slash. Remove if found.
string filenameInArchive = oneFile.Replace(#"/", #"\");
if (filenameInArchive.Substring(0, 1) == #"\")
filenameInArchive = filenameInArchive.Substring(1, filenameInArchive.Length - 1);
//blob needs slashes in opposite direction
string blobFile = oneFile.Replace(#"\", #"/");
//take first slash off of the (folder + file name) to access it directly in blob storage
if (blobFile.Substring(0, 1) == #"/")
blobFile = oneFile.Substring(1, oneFile.Length - 1);
var cloudBlockBlob = this.BlobStorageSource.GetBlobRef(blobFile);
if (!cloudBlockBlob.Exists()) //checking just in case
{
//go to the next file
//should probably trace log this
//add the file name with the fixed slashes rather than the raw, messed-up one
// so anyone looking at the list of files not found doesn't think it's because
// the slashes are different
filesNotFound.Add(blobFile);
}
else
{
//blob listing has files with forward slashes; that's what the zip file requires
//also, first character should not be a slash (removed it above)
ZipArchiveEntry newEntry = zipFile.CreateEntry(filenameInArchive, CompressionLevel.Optimal);
using (MemoryStream ms = new MemoryStream())
{
//download the blob to a memory stream
cloudBlockBlob.DownloadToStream(ms);
//write to the newEntry using a BinaryWriter and copying it 4k at a time
using (BinaryWriter entry = new BinaryWriter(newEntry.Open()))
{
//reset the memory stream's position to 0 and copy it to the zip stream in 4k chunks
//this keeps the process from taking up a ton of memory
ms.Position = 0;
byte[] buffer = new byte[4096];
bool copying = true;
while (copying)
{
int bytesRead = ms.Read(buffer, 0, buffer.Length);
if (bytesRead > 0)
{
entry.Write(buffer, 0, bytesRead);
}
else
{
entry.Flush();
copying = false;
}
}
}//end using for BinaryWriter
}//end using for MemoryStream
}//if file exists in blob storage
}//end foreach file
} //end of using ZipFileArchive
There are two things I noticed:
Once you read the blob contents in stream, you are not resetting that stream's position to 0. Thus all files in your zip are of zero bytes.
When calling AddEntry, you may want to specify the name of the blob there instead of "File"+cnt.
Please look at the code below. It's a console app that creates the zip file and writes it on the local file system.
static void SaveBlobsToZip()
{
string[] str = new string[] { "CodePlex.png", "DocumentDB.png" };
var account = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
var blobClient = account.CreateCloudBlobClient();
var container = blobClient.GetContainerReference("images");
using (var fs = new FileStream("D:\\output.zip", FileMode.Create))
{
fs.Position = 0;
using (var ms1 = new MemoryStream())
{
using (ZipFile zip = new ZipFile())
{
int cnt = 0;
foreach (string t in str)
{
var ms = new MemoryStream();
container.GetBlockBlobReference(t).DownloadToStream(ms);
ms.Position = 0;//This was missing from your code
zip.AddEntry(t, ms);//You may want to give the name of the blob here.
cnt++;
}
zip.Save(ms1);
}
ms1.Position = 0;
ms1.CopyTo(fs);
}
}
}
UPDATE
Here's the code in the MVC application (though I am not sure it is the best code :) but it works). I modified your code a little bit.
public ActionResult DownloadImagefilesAsZip()
{
string[] str = new string[] { "CodePlex.png", "DocumentDB.png" }; //repossitory.GetDocumentsUrlbyId(id);//output:Abc.txt,Pqr.Docx
CloudBlobContainer blobcontainer = GetCloudBlobContainer();// azureStorageUtility.GetCloudBlobContainer();
MemoryStream ms1 = new MemoryStream();
using (ZipFile zip = new ZipFile())
{
int cnt = 0;
foreach (string t in str)
{
var ms = new MemoryStream();
CloudBlockBlob blockBlob = blobcontainer.GetBlockBlobReference(t);
blockBlob.DownloadToStream(ms);
ms.Position = 0;//This was missing from your code
zip.AddEntry(t, ms);//You may want to give the name of the blob here.
cnt++;
}
zip.Save(ms1);
}
ms1.Position = 0;
return File(ms1, "application/zip", "all.zip");
}
I have seen people using ICSharpZip library, take a look at this piece of code
public void ZipFilesToResponse(HttpResponseBase response, IEnumerable<Asset> files, string zipFileName)
{
using (var zipOutputStream = new ZipOutputStream(response.OutputStream))
{
zipOutputStream.SetLevel(0); // 0 - store only to 9 - means best compression
response.BufferOutput = false;
response.AddHeader("Content-Disposition", "attachment; filename=" + zipFileName);
response.ContentType = "application/octet-stream";
foreach (var file in files)
{
var entry = new ZipEntry(file.FilenameSlug())
{
DateTime = DateTime.Now,
Size = file.Filesize
};
zipOutputStream.PutNextEntry(entry);
storageService.ReadToStream(file, zipOutputStream);
response.Flush();
if (!response.IsClientConnected)
{
break;
}
}
zipOutputStream.Finish();
zipOutputStream.Close();
}
response.End();
}
Taken from here generate a Zip file from azure blob storage files

Generate torrent links from server-side

I don't know a lot about torrents, at least not enough to understand how certain websites can offer both a normal download link and a torrent link to download a file uploaded by a user.
Is generating a torrent link something common and simple to achieve. Would I need a server installation?
I've made an ugly C# implementation from a Java source, and to make sure some of my encoded variables were correct, I used NBEncode from Lars Warholm.
// There are 'args' because I'm using it from command-line. (arg0 is an option not used here)
// Source file
args[1] = Directory.GetCurrentDirectory() + args[1];
// Name to give to the torrent file
args[2] = Directory.GetCurrentDirectory() + args[2];
var inFileStream = new FileStream(args[1], FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
var filename = args[2];
//BEncoding with NBEencode
var transform = new BObjectTransform();
MemoryStream s = new MemoryStream();
OSS.NBEncode.Entities.BDictionary bod = new OSS.NBEncode.Entities.BDictionary();
OSS.NBEncode.Entities.BDictionary meta = new OSS.NBEncode.Entities.BDictionary();
// Preparing the first part of the file by creating BEncoded objects
string announceURL = "https://www.mysite.com/announce";
int pieceLength = 512 * 1024;
bod.Value.Add(new BByteString("name"), new OSS.NBEncode.Entities.BByteString(filename));
bod.Value.Add(new BByteString("length"), new OSS.NBEncode.Entities.BInteger(inFileStream.Length));
bod.Value.Add(new BByteString("piece length"), new OSS.NBEncode.Entities.BInteger(pieceLength));
bod.Value.Add(new BByteString("pieces"), new BByteString(""));
meta.Value.Add(new BByteString("announce"), new BByteString(announceURL));
meta.Value.Add(new BByteString("info"), bod);
byte[] pieces = hashPieces(args[1], pieceLength);
transform.EncodeObject(meta, s);
s.Close();
// Notice that we finish with a dictionary entry of "pieces" with an empty string.
byte[] trs = s.ToArray();
s.Close();
inFileStream.Close();
// I don't know how to write array of bytes using NBEncode library, so let's continue manually
// All data has been written a MemoryStreamp, except the byte array with the hash info about each parts of the file
Stream st = new FileStream(filename + ".torrent", FileMode.Create);
BinaryWriter bw = new BinaryWriter(st);
// Let's write these Bencoded variables to the torrent file:
// The -4 is there to skip the current end of the file created by NBEncode
for (int i = 0; i < trs.Length - 4; i++)
{
bw.BaseStream.WriteByte(trs[i]);
}
// We'll add the length of the pieces SHA1 hashes:
var bt = stringToBytes(pieces.Length.ToString() + ":");
// Then we'll close the Bencoded dictionary with 'ee'
var bu = stringToBytes("ee");
// Let's append this to the end of the file.
foreach (byte b in bt)
{
bw.BaseStream.WriteByte(b);
}
foreach (byte b in pieces)
{
bw.BaseStream.WriteByte(b);
}
foreach (byte b in bu)
{
bw.BaseStream.WriteByte(b);
}
bw.Close();
st.Close();
// That's it.
}
Functions used:
private static byte[] stringToBytes(String str)
{
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
Byte[] bytes = encoding.GetBytes(str);
return bytes;
}
private static byte[] hashPieces(string file, int pieceLength)
{
SHA1 sha1 = new SHA1CryptoServiceProvider();
StreamReader inn = new StreamReader(file);
MemoryStream pieces = new MemoryStream();
byte[] bytes = new byte[pieceLength];
byte[] digest = new byte[20];
int pieceByteCount = 0, readCount = inn.BaseStream.Read(bytes, 0, pieceLength);
while (readCount != 0)
{
pieceByteCount += readCount;
digest = sha1.ComputeHash(bytes, 0, readCount);
if (pieceByteCount == pieceLength)
{
pieceByteCount = 0;
foreach (byte b in digest)
{
pieces.WriteByte(b);
}
}
readCount = inn.BaseStream.Read(bytes, 0, pieceLength - pieceByteCount);
}
inn.Close();
if (pieceByteCount > 0)
foreach (byte b in digest)
{
pieces.WriteByte(b);
}
return pieces.ToArray();
}
It depends on how you're trying to create it. If you run a website, and want to generate torrent files from uploaded files, then you'll obviously need server-side code.
Generating a torrent file involves: adding the files you want to the torrent, and adding tracker info. Some popular trackers are:
http://open.tracker.thepiratebay.org/announce
http://www.torrent-downloads.to:2710/announce
To create the .torrent file, you'll have to read the about the format of the file. A piece of Java that generates .torrent files is given at https://stackoverflow.com/a/2033298/384155

Unzipping on Windows Phone Mango

I am looking to extract a zip file from a url. What is the best way you would recommend to do this?
Basically, I want to point my phone app to a Zip url and have the files in it for processing.
Thanks in advance.
using ICSharpCode.SharpZipLib.Zip;
MemoryStream mem = new MemoryStream(data);
ZipFile zipped = null;
zipped = new ZipFile(mem);
IEnumerator enum1 = zipped.GetEnumerator();
while (enum1.MoveNext())
{
ZipEntry entry1 = (ZipEntry)enum1.Current;
Stream memst = zipped.GetInputStream(entry1);
long len = entry1.Size;
cmdresp = new byte[len];
memst.Read(cmdresp, 0, (int)len);
}

Resources