从URL将PDF转换为流

6
我有一个PDF文件,托管在http://test.com/mypdf.pdf

我该如何将PDF转换为Stream,并使用这个Stream将其转换回PDF?

我尝试了以下方法,但出现了异常(参见图像):

private static Stream ConvertToStream(string fileUrl)
{
    HttpWebResponse aResponse = null;
    try
    {
        HttpWebRequest aRequest = (HttpWebRequest)WebRequest.Create(fileUrl);
        aResponse = (HttpWebResponse)aRequest.GetResponse();
    }
    catch (Exception ex)
    {

    }

    return aResponse.GetResponseStream();
}

enter image description here


你到底想做什么?是将本地的PDF文件发送给用户以便他保存吗?还是接收用户上传的PDF文件并保存到本地磁盘?具体是什么? - balexandre
基本上,我会从 Web 服务中获取 PDF 的 URL,将其发送到我的应用程序中,在我的应用程序中将其转换为流并发送到另一个 Web 服务。然后,在那里,我将读取该流并将其转换回 PDF 并保存...希望这不会让人感到困惑。 - Zaki
2个回答

8
这将起作用:
private static Stream ConvertToStream(string fileUrl)
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(fileUrl);
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();

    try {
        MemoryStream mem = new MemoryStream();
        Stream stream = response.GetResponseStream();

        stream.CopyTo(mem,4096);

        return mem;
    } finally {
        response.Close();
    }
}

然而,你完全负责返回的内存流的生命周期。

更好的方法是:

private static void ConvertToStream(string fileUrl, Stream stream)
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(fileUrl);
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();

    try {
        Stream response_stream = response.GetResponseStream();

        response_stream.CopyTo(stream,4096);
    } finally {
        response.Close();
    }
}

您可以这样做:

using (MemoryStream mem = new MemoryStream()) {
    ConvertToStream('http://www.example.com/',mem);
    mem.Seek(0,SeekOrigin.Begin);

    ... Do something else ...
}

你也可以直接返回响应流,但是你需要检查它的生命周期,释放响应可能会释放流,因此需要进行内存复制。


我已经尝试了你的方法,但仍然在上面的截图中遇到了异常。 - Zaki
为什么要返回流?没有必要。如果属性出现错误,则说明该属性不可用。对于某些流实例,例如您无法设置位置或寻求,您正在尝试使用什么属性以及为什么? - Lloyd
好的,我已经成功完成了这个任务,但是当我将流发送到WCF时,出现了“Type 'System.Net.ConnectStream' cannot be serialized”的错误。请考虑使用DataContractAttribute属性标记它,并使用DataMemberAttribute属性标记您想要序列化的所有成员。 - Zaki
代码不正确。Stream没有包含CopyFrom的定义。 - ChatGPT
1
@MaxHodges 没错,这个问题已经存在了相当长的时间,真是太尴尬了!现在已经解决了,谢谢。 - Lloyd
显示剩余9条评论

5

您可能想要查看 WebClient.DownloadFile

您只需提供URL和本地文件名,它就会直接将文件保存到磁盘上,这可能会为您节省一两步。

您还可以尝试 WebClient.DownloadData,它将文件保存到内存中的byte[]中。

编辑

您没有指定您正在将文件发布到的Web服务的协议。最简单的形式(RESTful)就是将文件作为数据POST到另一个URL。以下是如何执行此操作。

using (WebClient wc = new WebClient())
{
    // copy data to byte[]
    byte[] data = wc.DownloadData("http://somesite.com/your.pdf");

    // POST data to another URL
    wc.Headers.Add("Content-Type","application/pdf");
    wc.UploadData("http://anothersite.com/your.pdf", data);
}

如果您正在使用SOAP,您需要将文件转换为Base64字符串,但希望您正在使用生成的客户端来处理这个问题。如果您能详细说明您要发送文件的Web服务类型,我可能可以提供更多信息。

我知道我可以这样做,但我的要求不是直接保存,因为我将把它发送到另一个服务器。 - Zaki
有什么阻止你使用 byte[] 吗?如果你不保存任何东西到磁盘上,我认为你肯定需要一个内存缓冲区。请查看我的更新答案。 - dana
请发送使用byte[]的示例。 - Zaki
我添加了一些示例代码,但不确定你要将文件发送到哪种类型的Web服务。如果有帮助,请告诉我。 - dana
这是一个WCF服务,当使用您提供的代码示例时,我可以看到数据具有字节,但在传输到WCF时,我遇到了以下错误,请问您能帮忙吗:格式化程序在尝试反序列化消息时引发了异常:尝试反序列化参数http://tempuri.org/:objToSave时出错。InnerException消息为“尝试反序列化类型为System.Collections.Generic.List`1的对象时出错”。 - Zaki

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接