C# .NET中添加FTP服务器文件为邮件附件的认证及实现问题
Alright, let's tackle this problem step by step. The issue here is that your current code is trying to access a local file using Server.MapPath, but the file you need is on an FTP server which requires authentication—so that's why you're hitting permission issues. Let's go over two solid solutions:
Solution 1: Download the FTP File to a Temporary Local Path
This approach involves downloading the file from the FTP server to a temporary directory on your server first, then attaching it to the email. After sending the email, you can clean up the temporary file.
using System.IO; using System.Net; using System.Net.Mail; // Configure your FTP details string ftpUrl = "ftp://your-ftp-server-address/Documents/quote.pdf"; string ftpUsername = "your-ftp-username"; string ftpPassword = "your-ftp-password"; // Create a temporary file path (uses system temp directory) string tempFilePath = Path.Combine(Path.GetTempPath(), Path.GetFileName(ftpUrl)); try { // Set up FTP request with authentication FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(ftpUrl); ftpRequest.Method = WebRequestMethods.Ftp.DownloadFile; ftpRequest.Credentials = new NetworkCredential(ftpUsername, ftpPassword); // Download the file to temp path using (FtpWebResponse ftpResponse = (FtpWebResponse)ftpRequest.GetResponse()) using (Stream ftpStream = ftpResponse.GetResponseStream()) using (FileStream tempFileStream = new FileStream(tempFilePath, FileMode.Create)) { ftpStream.CopyTo(tempFileStream); } // Attach the temp file and send the email mail.Body = body; Attachment attachment = new Attachment(tempFilePath); mail.Attachments.Add(attachment); SmtpServer.Send(mail); } finally { // Clean up the temporary file even if something goes wrong if (File.Exists(tempFilePath)) { File.Delete(tempFilePath); } }
Why this works:
- You explicitly authenticate with the FTP server to download the file.
- Using a temporary file keeps your server clean (the
finallyblock ensures it gets deleted regardless of success/failure).
Solution 2: Use the FTP Stream Directly (No Temporary File)
If you want to avoid writing a temporary file to disk, you can stream the file directly from the FTP server into the Attachment object. The key here is using the Attachment(Stream, string) constructor, which lets you pass the stream and specify the filename explicitly.
using System.Net; using System.Net.Mail; // Configure your FTP details string ftpUrl = "ftp://your-ftp-server-address/Documents/quote.pdf"; string ftpUsername = "your-ftp-username"; string ftpPassword = "your-ftp-password"; string attachmentFileName = Path.GetFileName(ftpUrl); // Extract filename from FTP URL try { // Set up FTP request with authentication FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(ftpUrl); ftpRequest.Method = WebRequestMethods.Ftp.DownloadFile; ftpRequest.Credentials = new NetworkCredential(ftpUsername, ftpPassword); // Get the FTP response stream using (FtpWebResponse ftpResponse = (FtpWebResponse)ftpRequest.GetResponse()) using (Stream ftpStream = ftpResponse.GetResponseStream()) { // Create attachment directly from the stream, specifying the filename Attachment attachment = new Attachment(ftpStream, attachmentFileName); mail.Attachments.Add(attachment); // Send the email (keep the stream open until send completes) mail.Body = body; SmtpServer.Send(mail); } } catch (WebException ex) { // Handle FTP errors (e.g., file not found, invalid credentials) Console.WriteLine($"FTP Error: {ex.Message}"); }
Important Notes:
- The FTP stream must stay open until the email is sent, so we wrap everything in a
usingblock to ensure proper cleanup after sending. - Using
Path.GetFileName(ftpUrl)automatically extracts the filename from your FTP URL, so you don't have to hardcode it. - Add error handling (like the
WebExceptioncatch) to handle cases where the FTP server is unreachable, the file doesn't exist, or credentials are invalid.
Which solution should you choose?
- Use Solution 1 for large files: Downloading to a temp file avoids holding the entire file in memory.
- Use Solution 2 for small to medium files: It's more efficient and skips writing to disk entirely.
内容的提问来源于stack exchange,提问作者Zayd Chopdat

